<template>
<div class="reference">
  <el-select v-model="getValue"
             style="width: 100%;"
             @change="change"
             :collapse-tags="multiple"
             :multiple="multiple"
             placeholder="请选择参照">
    <el-option
      v-for="item in getData"
      :key="item[operation.value]"
      :label="item[operation.label]"
      :value="item[operation.value]">
    </el-option>
  </el-select>
  <i @click="openDialog" class="el-icon-s-unfold icon"></i>
  <el-dialog
    size="small"
    :title="title"
    :visible.sync="dialogVisible"
    width="80%"
    :before-close="handleClose">
    <component :selectList="options"
               :type="multiple ? 2 : 1"
               ref="component"
               v-if="dialogVisible"
               :is="currentComponent"></component>
    <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="ok">确 定</el-button>
  </span>
  </el-dialog>
</div>
</template>

<script>

export default {
  name: 'reference',
  model:{
    event:"input",
    prop:"options",
  },
  props:{
    //参照标题
    title:{
      type:String,
      default:"参照"
    },
    //参照懒加载函数
    component:{
      type:Function,
      required:true
    },
    //指定options的结构 value为选中的元素key  label为选中的元素展示名称
    operation:{
      type:Object,
      default: () => {return { value:"id", label:"name" }}
    },
    //是否多选
    multiple:{
      type:Boolean,
      default:false
    },
    showReferenceBox:{
      type:Boolean,
      default:true
    },
    //选中的数据，使用v-model传递，单选传递obj,多选传递array,operation指定其结构
    options:{
      type : Array | Object,
      default : () => {}
    }
  },
  computed:{
    getData(){
      if(this.options instanceof Array)
        return this.options
      else
        return [this.options]
    },
    getValue(){
      if(this.multiple)
        this.value = this.options.map(item => item[this.operation.value])
      else
        this.value = this.options[this.operation.value]
      return this.value;
    }
  },
  data(){
    return {
      value:null,
      label:"",
      dialogVisible:false,
      currentComponent:null,
    }
  },
  /**
   * 初始化参照信息
   */
  created() {

  },

  methods: {
    /**
     * 过滤选中的
     * @param e
     */
    change(e){
      console.log("触发过滤选中")
      if(this.multiple)
        this.$emit('input', this.options.filter(item => e.includes(item[this.operation.value])));
    },
    /**
     * 打开参照
     */
    openDialog(){
      this.loadComponent();
    },
    /**
     * 加载参照
     */
    loadComponent() {
     if(this.currentComponent == null ){
       this.dialogVisible = false;
       const loading = this.$loading({
         lock: true,
         text: 'Loading',
         spinner: 'el-icon-loading',
         background: 'rgba(0, 0, 0, 0.7)'
       });
       this.component().then(res => {
         this.currentComponent = res.default;
       }).finally(() => {
         loading.close();
         this.dialogVisible = true;
       })
     }else {
       console.log("已加载")
       this.dialogVisible = true;
     }
    },
    updateValue(newValue) {
      console.log("参照带出" + newValue)
      if(this.multiple){
        const ids = newValue.map(item => item[this.operation.value])
        console.log(newValue)
        //双向绑定 options
        this.$emit('input', newValue);
        this.$emit("updateRef",newValue)
        this.value = ids
      }else {
        console.log(newValue)
        //双向绑定 options
        this.$emit('input', newValue);
        this.$emit("updateRef",newValue)
        this.value = newValue[this.operation.value]
      }

    },
    handleClose(done) {
      done();
    },
    ok(){
      const info = this.$refs.component.getReferenceInfo();
      this.updateValue(info)
      this.dialogVisible = false
    }
  }
}
</script>

<style scoped lang="scss">
.reference{
  width: 100%;
  display: flex;
  align-items: center;
  .icon{
    //style="cursor: pointer;font-size: 20px"
    font-size: 20px !important;
    position: relative;
    left: -35px;
    color: #a69d9d;
  }

}
</style>
